package com.nulldev.util.java.swing.extSwing.lookandfeel.themes;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.RenderingHints;
import java.awt.SystemColor;
import java.util.ArrayList;

import javax.swing.CellRendererPane;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JEditorPane;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

import com.nulldev.util.java.JVMUtil;
import com.nulldev.util.java.swing.SwingUtil;
import com.nulldev.util.java.swing.SwingUtil.ScrollDirection;
import com.nulldev.util.java.swing.canvas.SmoothCanvas;
import com.nulldev.util.java.swing.extSwing.PolyBorder;
import com.nulldev.util.java.swing.extSwing.RoundedBorder;
import com.nulldev.util.java.swing.font.FontManager;
import com.nulldev.util.java.swing.font.SWTItem;
import com.nulldev.util.java.utils.color.ColorUtil;
import com.nulldev.util.other.ArrayUtils;

import sun.swing.SwingUtilities2;

public class ThemeApplier {
	
	public static boolean useSystem = false;
	/**
	 * Adding a more modern look to Java Swing
	 * @since nullUtil 2.6 beta
	 */
	public static boolean usePolyAPI = true;
	//public static Font font = FontManager.getFontSet();
	
	public static void applyTheme(final Container c) {
		applyTheme(defaultTheme, c, false, true);
	}
	
	public static void applyTheme(final Container c, final boolean enableJPane) {
		applyTheme(defaultTheme, c, false, enableJPane);
	}
	
	public static void applyTheme(final Theme theme, final Container c) {
		applyTheme(theme, c, false, true);
	}

	public static void applyTheme(final Theme theme, final Container c, final boolean skipTransparent, final boolean enableJEditorPane) {
		FontManager.registerAll(c, true);
		
		SwingUtil.enableAA();
		SwingUtil.enableJSO();
		
		// Init.openChat_pref.readOptionBoolean("themeing.useSystem")
		final boolean useSystem = ThemeApplier.useSystem;
		if (useSystem) {
			try {
				UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			} catch (final Exception e) {}
			return;
		}
		final Color back = UIManager.getColor("text"); //ColorUtil.invert(foreground); //UIManager.getColor("window");
		final Color foreground = ColorUtil.invertd(back); //UIManager.getColor("text");
		final ArrayList<Component> items = FontManager.getAllComponents(c);
		int its = 0;
		if (c != null) {
			c.setFont(FontManager.getFontSet());
			if (!(c instanceof JTabbedPane)) {
				c.setForeground((useSystem ? foreground : theme.getForeground()));
			}else {
				c.setForeground(theme.getForeground());
			}
			if (c.getBackground() != ColorUtil.TRANSPARENT && !skipTransparent) {
				c.setBackground((useSystem ? back : theme.getBackground()));
			}
		}
		while (!items.isEmpty()) {
			// haHAA
			for (final Component cx : (ArrayList<Component>) items.clone()) {
				//System.out.println(cx.getClass().getName());
				if (cx instanceof SmoothCanvas) {
					if (((SmoothCanvas) cx).getComponentCount() > 0) {
						items.addAll(ArrayUtils.toArrayList(((SmoothCanvas) cx).getComponents()));
					}
					items.remove(0);
					continue;
				}
				// Patch for Linux Desktop Enviroments that are special.
				// (Added in 2.6 beta) Also for special Windows and other special instances
				if (cx instanceof JComponent) {
					try {
						((JComponent) cx)
						.putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, new SwingUtilities2.AATextInfo(
								RenderingHints.VALUE_TEXT_ANTIALIAS_ON, null));
					}catch (Exception e) {
						e.printStackTrace();
					}
				}
				//
				if (cx instanceof JMenu) {
					try {
						items.addAll(ArrayUtils.toArrayList(((JMenu) cx).getMenuComponents()));
						if (cx.getBackground() != ColorUtil.TRANSPARENT && !skipTransparent) {
							cx.setBackground((useSystem ? back : theme.getBackground()));
						}else if (cx.getBackground() == SystemColor.windowBorder) {
							cx.setForeground((useSystem ? foreground : theme.getForeground()));
						}
						((JMenu) cx).setOpaque(true);
						
					}catch (Exception e) {
						e.printStackTrace();
						if (cx.getBackground() != ColorUtil.TRANSPARENT && !skipTransparent) {
							cx.setBackground((useSystem ? back : theme.getBackground()));
						}else if (cx.getBackground() == SystemColor.windowBorder) {
							cx.setForeground((useSystem ? foreground : theme.getForeground()));
						}
						cx.setForeground((useSystem ? foreground : theme.getForeground()));
						((JMenu) cx).setOpaque(true);
					}
				}
				if (cx instanceof JToggleButton) {
					final JToggleButton jtgb = (JToggleButton) cx;
					jtgb.setFocusable(false);
					jtgb.putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, new SwingUtilities2.AATextInfo(
							RenderingHints.VALUE_TEXT_ANTIALIAS_ON, null));
					items.addAll(ArrayUtils.toArrayList(jtgb.getComponents()));
				}
				if (cx instanceof JEditorPane) {
					final JEditorPane ed = (JEditorPane) cx;
					if (enableJEditorPane) {
						ed.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
					}
				}
				if (cx instanceof JButton && !(cx instanceof JToggleButton)) {
					final JButton btn = (JButton) cx;
					btn.setBorder(new RoundedBorder(5));
					btn.setFocusable(false);
				}
				if (cx instanceof JCheckBox) {
					cx.setFocusable(false);
				}
				if (cx instanceof JComboBox) {
					cx.setFocusable(false);
					items.addAll(ArrayUtils.toArrayList(((JComboBox) cx).getComponents()));
				}
				if (cx instanceof JTabbedPane) {
					cx.setFocusable(false);
				}
				if (cx instanceof JTable) {
					final JTable jt = (JTable) cx;
					items.addAll(ArrayUtils.toArrayList(jt.getComponents()));
					jt.putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, new SwingUtilities2.AATextInfo(
							RenderingHints.VALUE_TEXT_ANTIALIAS_ON, null));
					if (jt.getTableHeader() != null) {
						jt.getTableHeader().setDefaultRenderer(new DefaultTableCellRenderer() {
							@Override
							public Component getTableCellRendererComponent(JTable table, Object value,
			                          boolean isSelected, boolean hasFocus, int row, int column) {
								final Component out = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
								if (out instanceof JComponent) {
									((JComponent) out).putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, new SwingUtilities2.AATextInfo(
											RenderingHints.VALUE_TEXT_ANTIALIAS_ON, null));
								}
								return out;
							}
						});
						jt.getTableHeader().setFont(FontManager.getFontSet());
						jt.getTableHeader().setForeground(theme.getForeground());
						jt.getTableHeader().setBackground((useSystem ? back : theme.getBackground()));
						jt.getTableHeader().putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, new SwingUtilities2.AATextInfo(
								RenderingHints.VALUE_TEXT_ANTIALIAS_ON, null));
					}
				}
				if (cx instanceof JScrollPane) {
					SwingUtil.scroll((JScrollPane) cx, ScrollDirection.UP);
				}
				if (cx instanceof SmoothCanvas) {
					final SmoothCanvas s = (SmoothCanvas) cx;
					s.setAAEnabled(true);
					//continue;
				}
				
				cx.setFont(FontManager.getFontSet());
				if (cx instanceof JSeparator) {
					cx.setForeground(ColorUtil.TRANSPARENT);
					cx.setBackground(ColorUtil.TRANSPARENT);
				}else {
					if (cx instanceof JToggleButton && (theme.equals(Theme.FAIR_GREY))) {
						cx.setForeground(Color.YELLOW);
					}else {
						if (!(cx instanceof JTabbedPane)) {
							cx.setForeground((useSystem ? foreground : theme.getForeground()));
						}else {
							if (cx instanceof JProgressBar) {
								cx.setForeground(Color.yellow);
							}else {
								cx.setForeground(theme.getForeground());
							}
						}
					}
					if (cx.getBackground() != ColorUtil.TRANSPARENT && !skipTransparent) {
						cx.setBackground((useSystem ? back : theme.getBackground()));
					}
				}
				if (usePolyAPI) {
					// ThemeApplier2: Poly/Flat theme API
					// Added in nullUtil 2.6 BETA build 220
					// remove extra borders
					if ((cx instanceof JComponent) &&
						!(cx instanceof JButton) && !(cx instanceof JTextField) && !(cx instanceof JDesktopPane)) {
						((JComponent) cx).setBorder(null);
					}
					if (cx instanceof JTextField) {
						if (((JTextField)cx).isEditable()) {
							((JComponent) cx).setBorder(new PolyBorder(Color.orange));
						}else {
							//((JComponent) cx).setBorder(new RoundedBorder(1));
						}
					}
				}
				items.remove(0);
			}	
		}
	}

	public static Theme defaultTheme = Theme.BLACK;
	public static void setTheme(final Theme t) {
		defaultTheme = t;
	}

	public static void applyAll(final Theme theme) {
		applyAll(theme, false);
	}

	public static void applyAll(final Theme theme, final boolean skipTransparent) {
		final Color back = UIManager.getColor("text"); //ColorUtil.invert(foreground); //UIManager.getColor("window");
		final Color foreground = ColorUtil.invertd(back); //UIManager.getColor("text");
		for (final SWTItem item : FontManager.getModules()) {
			final Component cx = item.item();
			if (cx instanceof SmoothCanvas) {
				return;
			}
			// Patch for Linux Desktop Enviroments that are special.
			if (cx instanceof JComponent) {
				try {
					((JComponent) cx)
					.putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, new SwingUtilities2.AATextInfo(
							RenderingHints.VALUE_TEXT_ANTIALIAS_ON, null));
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
			//
			if (cx instanceof JMenu) {
				try {
					//items.addAll(ArrayUtils.toArrayList(((JMenu) cx).getMenuComponents()));
					if (cx.getBackground() != ColorUtil.TRANSPARENT && !skipTransparent) {
						cx.setBackground((useSystem ? back : theme.getBackground()));
					}else if (cx.getBackground() == SystemColor.windowBorder) {
						cx.setForeground((useSystem ? foreground : theme.getForeground()));
					}
					((JMenu) cx).setOpaque(true);
					
				}catch (Exception e) {
					e.printStackTrace();
					if (cx.getBackground() != ColorUtil.TRANSPARENT && !skipTransparent) {
						cx.setBackground((useSystem ? back : theme.getBackground()));
					}else if (cx.getBackground() == SystemColor.windowBorder) {
						cx.setForeground((useSystem ? foreground : theme.getForeground()));
					}
					cx.setForeground((useSystem ? foreground : theme.getForeground()));
					((JMenu) cx).setOpaque(true);
				}
			}
			if (cx instanceof JToggleButton) {
				final JToggleButton jtgb = (JToggleButton) cx;
			}
			if (cx instanceof JEditorPane) {
				final JEditorPane ed = (JEditorPane) cx;
				ed.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
			}
			if (cx instanceof JButton) {
				final JButton btn = (JButton) cx;
				btn.setBorder(new RoundedBorder(5));
				btn.setFocusable(false);
			}
			if (cx instanceof JTextField) {
				//cx.setFocusable(false);
			}
			if (cx instanceof JCheckBox) {
				cx.setFocusable(false);
			}
			if (cx instanceof JComboBox) {
				cx.setFocusable(false);
			}
			if (cx instanceof JTabbedPane) {
				cx.setFocusable(false);
			}
			if (cx instanceof JScrollPane) {
				SwingUtil.scroll((JScrollPane) cx, ScrollDirection.UP);
			}
			cx.setFont(FontManager.getFontSet());
			if (cx instanceof JToggleButton && (theme.equals(Theme.FAIR_GREY))) {
				cx.setForeground(Color.YELLOW);
			}else {
				if (!(cx instanceof JTabbedPane)) {
					cx.setForeground((useSystem ? foreground : theme.getForeground()));
				}else if (cx instanceof JTabbedPane) {
					cx.setForeground(Color.cyan);
				}else {
					cx.setForeground(theme.getForeground());
				}
			}
			if (cx.getBackground() != ColorUtil.TRANSPARENT && !skipTransparent) {
				cx.setBackground((useSystem ? back : theme.getBackground()));
			}
			//items.remove(0);
		}
	}
}
